package com.wdb007.venus.svc.biz.order;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.wdb007.venus.svc.biz.manager.ConfigInfoManager;
import com.wdb007.venus.svc.biz.utils.DateFormatUtil;
import com.wdb007.venus.svc.dal.account.dao.AccountCashDAO;
import com.wdb007.venus.svc.dal.account.dao.AccountCashLogDAO;
import com.wdb007.venus.svc.dal.account.model.AccountCashDO;
import com.wdb007.venus.svc.dal.account.model.AccountCashLogDO;
import com.wdb007.venus.svc.dal.book.dao.BookEntityDAO;
import com.wdb007.venus.svc.dal.book.dao.BookGridTransDAO;
import com.wdb007.venus.svc.dal.book.dao.BookInfoDAO;
import com.wdb007.venus.svc.dal.book.model.BookChargeDO;
import com.wdb007.venus.svc.dal.book.model.BookEntityDO;
import com.wdb007.venus.svc.dal.book.model.BookGridTransDO;
import com.wdb007.venus.svc.dal.book.model.BookInfoDO;
import com.wdb007.venus.svc.dal.order.dao.BookGridChargeLogDAO;
import com.wdb007.venus.svc.dal.order.dao.OrderInfoDAO;
import com.wdb007.venus.svc.dal.order.dao.OrderTransDAO;
import com.wdb007.venus.svc.dal.order.model.BookGridChargeLogDO;
import com.wdb007.venus.svc.dal.order.model.OrderInfoDO;
import com.wdb007.venus.svc.dal.order.model.OrderTransDO;
import com.wdb007.venus.svc.dal.user.dao.UserCostFlagDAO;
import com.wdb007.venus.svc.dal.user.dao.UserInfoDAO;
import com.wdb007.venus.svc.dal.user.dao.UserPointDAO;
import com.wdb007.venus.svc.dal.user.dao.UserPointLogDAO;
import com.wdb007.venus.svc.dal.user.dao.UserReadStatisticsDAO;
import com.wdb007.venus.svc.dal.user.dao.UserWishListDAO;
import com.wdb007.venus.svc.dal.user.model.UserCostFlagDO;
import com.wdb007.venus.svc.dal.user.model.UserInfoDO;
import com.wdb007.venus.svc.dal.user.model.UserPointDO;
import com.wdb007.venus.svc.dal.user.model.UserPointLogDO;
import com.wdb007.venus.svc.dal.user.model.UserReadStatisticsDO;
import com.wdb007.venus.svc.dal.user.model.UserWishListDO;
import com.wdb007.venus.svc.facade.OrderService;
import com.wdb007.venus.svc.facade.WxAPPMessagePushService;
import com.wdb007.venus.svc.facade.constant.BizConstants;
import com.wdb007.venus.svc.facade.exception.BizException;
import com.wdb007.venus.svc.facade.order.model.OrderInfoDTO;
import com.wdb007.venus.svc.facade.order.model.OrderTransDTO;

@Service("orderService")
public class OrderServiceImpl implements OrderService {
	
	private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);
	@Autowired
	private OrderInfoDAO orderInfoDAO ;
	
	@Autowired
	private OrderTransDAO orderTransDAO;
	
	@Autowired
	private AccountCashDAO accountCashDAO;
	
	@Autowired
	private AccountCashLogDAO accountCashLogDAO;
	
	@Autowired
	private BookGridTransDAO bookGridTransDAO;
	
	@Autowired
	private BookGridChargeLogDAO bookGridChargeLogDAO;
	
	@Autowired
	private UserWishListDAO userWishListDAO;
	
	@Autowired
	private BookEntityDAO bookEntityDAO;
	
	@Autowired
	private UserCostFlagDAO userCostFlagDAO;
	
	@Autowired
	private BookInfoDAO bookInfoDAO;
	
	@Autowired
	private UserPointDAO userPointDAO;
	@Autowired
	private UserPointLogDAO userPointLogDAO;
	@Autowired
	private UserInfoDAO userInfoDAO;
	
	@Autowired
	private WxAPPMessagePushService WxAPPMessagePushService;
	
	@Autowired
	private UserReadStatisticsDAO userReadStatisticsDAO;
	@Autowired
	private ConfigInfoManager configInfoManager;
	
	@Override
	public void setupOrder(OrderInfoDTO orderInfo)  throws BizException{
		OrderInfoDO orderInfoDO = new OrderInfoDO();
		BeanUtils.copyProperties(orderInfo, orderInfoDO);
		orderInfoDAO.insert(orderInfoDO);
		orderInfo.setId(orderInfoDO.getId());
	}

	@Override
	public void setupOrderTrans(OrderTransDTO orderTrans)  throws BizException{
		//1.根据rfid_code 和 trans_status =20（计费中） 查询出该条
		orderTrans.setTransStatus(BizConstants.ORDER_TRANS_STATUS_20);
		orderTrans.setChargeCount(0);
		OrderTransDO orderTransDO = new OrderTransDO();
		BeanUtils.copyProperties(orderTrans, orderTransDO);
		orderTransDAO.insert(orderTransDO);
	}

	@Override
	public void finishOrderTrans(OrderTransDTO orderTrans, Integer flag, Long returnUserId)  throws BizException{
		logger.info("finishOrderTrans's params: {}, flag(0--表示正常盘点   1--表示再次盘点): {}， 归还时userId[{}]", JSON.toJSONString(orderTrans), flag, returnUserId);
		OrderTransDO query = new OrderTransDO();
		query.setRfidCode(orderTrans.getRfidCode());
		query.setTransStatus(BizConstants.ORDER_TRANS_STATUS_20);
		
		OrderTransDO queryResult = orderTransDAO.getByRfidCodeAndStatus(query);
		//如果查询不到数据，则说明是第一次上架的图书。不参与计费。
		OrderTransDO query22 = new OrderTransDO();
		query22.setRfidCode(orderTrans.getRfidCode());
		query22.setTransStatus(BizConstants.ORDER_TRANS_STATUS_40);
		OrderTransDO queryResult2 = orderTransDAO.getByRfidCodeAndStatus(query22);
		if(queryResult == null && queryResult2 == null) {
			UserInfoDO userInfo = userInfoDAO.get(returnUserId);
			if(1 == userInfo.getUserType()) {
				OrderTransDO ot = new OrderTransDO();
				ot.setBorrowDate(new Date());
				ot.setBorrowPrice(new BigDecimal("0.00"));
				ot.setChargeCount(0);
				ot.setCreateTime(new Date());
				ot.setCostFlag(2);
				ot.setGridCode(orderTrans.getRestituteGridCode());
				ot.setRestituteGridCode(orderTrans.getRestituteGridCode());
				ot.setShelfCode(orderTrans.getRestituteShelfCode());
				ot.setRestituteShelfCode(orderTrans.getRestituteShelfCode());
				ot.setUserId(returnUserId);
				ot.setRfidCode(orderTrans.getRfidCode());
				ot.setGridTransId(orderTrans.getGridTransId());
				ot.setTransStatus(BizConstants.ORDER_TRANS_STATUS_30);
				ot.setTransAmount(new BigDecimal("0.00"));
				ot.setModifyTime(new Date());
				orderTransDAO.insert(ot);
			} else {
				logger.error("根据rfid[{}]以及trans_status状态为20 查询不到 交易流水", orderTrans.getRfidCode());
			}
			return ;
		}
		if(null != queryResult2) {
			logger.info("根据rfidCode[{}]以及trans_status状态为30,查询到流水,直接更新状态");
			queryResult2.setModifyTime(new Date());
			queryResult2.setTransStatus(BizConstants.ORDER_TRANS_STATUS_30);
			queryResult2.setGridTransId(orderTrans.getGridTransId());
			queryResult2.setRestituteGridCode(orderTrans.getRestituteGridCode());
			queryResult2.setRestituteShelfCode(orderTrans.getRestituteShelfCode());
			orderTransDAO.update(queryResult2);
			return ;
		}
		Long userid = queryResult.getUserId();
		UserInfoDO userInfo = userInfoDAO.get(userid);
		Date now = new Date();
		queryResult.setModifyTime(now);
		queryResult.setRestituteGridCode(orderTrans.getRestituteGridCode());
		queryResult.setRestituteShelfCode(orderTrans.getRestituteShelfCode());
		queryResult.setGridTransId(orderTrans.getGridTransId());
		queryResult.setTransStatus(BizConstants.ORDER_TRANS_STATUS_30);	//已完成
		if(1 == userInfo.getUserType()) {
			queryResult.setChargeCount(0);
			queryResult.setCostFlag(2);
			queryResult.setTransAmount(new BigDecimal("0.00"));
			queryResult.setModifyTime(new Date());
			orderTransDAO.update(queryResult);
			return ;
		}
		
		Long orderId = queryResult.getOrderId();
	
		//更新用户扣款标志表
		BigDecimal cost_per_book_per_day = queryResult.getBorrowPrice();
		Long millSeconds = now.getTime() - queryResult.getCreateTime().getTime() ;
		
		int minutes = (int)(millSeconds / 1000 / 60) ;
		int hours = (int)Math.ceil(Double.parseDouble(millSeconds+"") / 1000 / 60 / 60);
		BigDecimal cost = null ;	//总扣费金额
		BigDecimal per_cost = cost_per_book_per_day	;//	本次扣费金额
		Integer costFlag = 0;	//默认正常收费
		//如果借阅时间小于5分钟，则不进行收费
		logger.info("=====间隔时间 [{}] 分钟 ", minutes);
		int chargeCount = queryResult.getChargeCount();
		BookEntityDO bookEntity = bookEntityDAO.get(queryResult.getRfidCode());
		BookInfoDO bookInfo = bookInfoDAO.get(bookEntity.getIsbnNo());
		if(null == bookInfo) {	//FIXME 图书信息不存在时，目前不进行计费，计费金额为0
			cost = new BigDecimal(0);
			per_cost = new BigDecimal(0);
		}else if(minutes < 5) {
			cost = new BigDecimal(0);
			per_cost = new BigDecimal(0);
			//FIXME 如果时再次盘点，得到的时间小于5分钟，则直接删除掉该记录
			if(1 == flag) {
				//1.直接删除掉该记录
				orderTransDAO.remove(queryResult.getId());
				return ;
			}
		}else if(hours - 24*chargeCount <= 0) {
				cost = queryResult.getTransAmount();
				per_cost = new BigDecimal(0);
		}else {
			//FIXME 如果扣款扣到一半时，50元金额没了的话，怎么处理
			UserCostFlagDO userCostFlagResult = getUserCostFlag(userid);
			BigDecimal cost_per_book_over_3 = new BigDecimal(configInfoManager.getValue("cost_per_book_over_3"));
			if(null != userCostFlagResult) {
				Integer costOrder = userCostFlagResult.getCostOrder();
				//如果已经是月卡用户或者年卡用户，并且borrowPrice为0，则不进行收费
				if(new BigDecimal("0.00").compareTo(cost_per_book_per_day) == 0 && (3 == costOrder || 4 == costOrder)) {
					//FIXME 用户如果借了5本书，但是年卡今天到期时，多出的两本书如何收费？还是不收费。
					if(3 == costOrder) {
						costFlag = 2;
					}else {
						costFlag = 3;
					}
					if(3 == costOrder) {//如果年卡到期之后，超过三本的图书按照每天2元收费
						int count = orderTransDAO.countByVIPCharge(userid);
						if(count > 3) {
							OrderTransDO query2 = new OrderTransDO();
							query2.setUserId(userid);
							query2.setId(queryResult.getId());
							Integer rank = orderTransDAO.getRankByVIPQuery(query2);
							if(rank != null && rank.intValue() > 3) {
								cost_per_book_per_day = cost_per_book_over_3;
								costFlag = 1;
								per_cost = cost_per_book_per_day;
							}
						}
					}
				}else if(4 == costOrder) { //如果是年卡会员，并且扣费金额不为0,判断用户在借图书使用vip计费的本书
					int count = orderTransDAO.countByVIPCharge(userid);
					int gridTransCount = orderTransDAO.countByGridTransId(orderTrans.getGridTransId());
					if(count < 5 && gridTransCount < 5) {
						cost_per_book_per_day = new BigDecimal("0.00");
						per_cost = cost_per_book_per_day;
						costFlag = 3;
					}
				}else if(3 == costOrder) { //如果是月卡会员，并且扣费金额不为0,判断用户在借图书使用vip计费的本书
					int count = orderTransDAO.countByVIPCharge(userid);
					int gridTransCount = orderTransDAO.countByGridTransId(orderTrans.getGridTransId()); 
					if(count < 3 && gridTransCount < 3) {
						cost_per_book_per_day = new BigDecimal("0.00");
						per_cost = cost_per_book_per_day;
						costFlag = 2;
					}
				}else {	//FIXME 如果用户年卡到期，或者月卡到期，该如何扣费？
					BigDecimal sub = null;
					if(cost_per_book_over_3.compareTo(cost_per_book_per_day) != 0) {
						OrderTransDO q = new OrderTransDO();
						q.setUserId(userid);
						q.setBorrowPrice(cost_per_book_per_day);
						costFlag = 0;
						int count = orderTransDAO.countByUserIdAndBorrowPrice(q);
						if(count > 3) {	//如果大于3本，则扣费金额为2元每天
							cost_per_book_per_day = cost_per_book_over_3;
							per_cost = cost_per_book_per_day;
							costFlag = 1;
						}else {
							sub = userCostFlagResult.getRemainder().subtract(userCostFlagResult.getPrice());
							cost_per_book_per_day = userCostFlagResult.getPrice();
							per_cost = cost_per_book_per_day;
						}
					}else {
						sub = userCostFlagResult.getRemainder().subtract(cost_per_book_over_3);
						costFlag = 1;
					}
					userCostFlagResult.setRemainder(sub);
					userCostFlagResult.setModifyTime(new Date());
					if(sub.compareTo(new BigDecimal("0.00")) <= 0) {
						userCostFlagResult.setValidFlag(0);
					}
					userCostFlagDAO.update(userCostFlagResult);
				}
			}else if(new BigDecimal("0.00").compareTo(cost_per_book_per_day) == 0) { //如果年卡或者月卡到期，并且从userCostFlag表中查不到数据的话，则直接扣除余额
				OrderTransDO q = new OrderTransDO();
				q.setUserId(userid);
				q.setBorrowPrice(new BigDecimal("0.00"));
				int price0Count = orderTransDAO.countByUserIdAndBorrowPrice(q);
				q.setBorrowPrice(new BigDecimal("1"));
				int price1Count = orderTransDAO.countByUserIdAndBorrowPrice(q);
				int count = price0Count + price1Count;
				if(count > 3) {
					OrderTransDO rankQuery = new OrderTransDO();
					rankQuery.setUserId(userid);
					rankQuery.setId(queryResult.getId());
					Integer rank = orderTransDAO.getRankByVIPQuery(rankQuery);
					if(rank != null && rank < 4) {
						cost_per_book_per_day = new BigDecimal(configInfoManager.getValue("cost_per_book_per_day"));
						costFlag = 0;
						per_cost = cost_per_book_per_day;
					}else {
						cost_per_book_per_day = cost_per_book_over_3;
						costFlag = 1;
						per_cost = cost_per_book_per_day;
					}
				}else {
					cost_per_book_per_day = new BigDecimal(configInfoManager.getValue("cost_per_book_per_day"));
					per_cost = cost_per_book_per_day;
					costFlag = 0;
				}
			}else if(cost_per_book_per_day.compareTo(cost_per_book_over_3) == 0) {
				OrderTransDO q = new OrderTransDO();
				q.setUserId(userid);
				q.setBorrowPrice(new BigDecimal("1.00"));
				int price1Count = orderTransDAO.countByUserIdAndBorrowPrice(query);
				if(price1Count < 3) {
					cost_per_book_per_day = new BigDecimal("1.00");
					costFlag = 0;
				}
			}
			
			if(cost_per_book_per_day.compareTo(cost_per_book_over_3) == 0) {
				costFlag = 1;
			}
			if(null != queryResult.getTransAmount())
				cost = per_cost.add(queryResult.getTransAmount());
			else
				cost = per_cost;
			
			chargeCount = chargeCount+1;
		}
		
		logger.info("本次扣费金额: per_cost===== {} ", per_cost);
		queryResult.setChargeCount(chargeCount);
		queryResult.setTransAmount(cost);
		orderTrans.setOrderId(orderId);
		orderTrans.setCostFlag(costFlag);
		//现金账户的扣减
		if(null != per_cost && new BigDecimal("0.00").compareTo(per_cost) != 0) {
			AccountCashDO accountCash = accountCashDAO.getByUserid(userid);
			accountCash.setCashAmount(accountCash.getCashAmount().subtract(per_cost));
			accountCash.setModifyTime(now);
			accountCashDAO.update(accountCash);
			Long accountCashId = accountCash.getId();
			//增加 现金账户记录
			AccountCashLogDO accountCashLog = new AccountCashLogDO();
			accountCashLog.setAccountCashId(accountCashId);
			accountCashLog.setChangeAmount(per_cost);
			accountCashLog.setChargeType(BizConstants.ACCOUNT_CASH_CHARGE_TYPE_50);
			accountCashLog.setOperType(BizConstants.ACCOUNT_CASH_OPER_TYPE_20);
			accountCashLog.setCreateTime(now);
			accountCashLog.setOrderId(queryResult.getId());
			accountCashLogDAO.insert(accountCashLog);
			queryResult.setPaySerialNo(accountCashLog.getId());
		}
		//orderTransDAO增加支付流水号以及支付时间
		queryResult.setPayTime(now);
		queryResult.setBorrowPrice(cost_per_book_per_day);
		orderTransDAO.update(queryResult);
		
		//更新用户心愿单表
		UserWishListDO userWishListquery = new UserWishListDO();
		userWishListquery.setUserId(userid);
		userWishListquery.setStatus(1);
		String isbn = bookEntityDAO.get(orderTrans.getRfidCode()).getIsbnNo();
		userWishListquery.setIsbn(isbn);
		UserWishListDO userWishListResult = userWishListDAO.getByCondition(userWishListquery);
		if(null != userWishListResult) {
			userWishListResult.setStatus(2);
			userWishListResult.setModifyTime(new Date());
			userWishListDAO.update(userWishListResult);
		}
		if(minutes >= 30) {
			UserPointDO userPoint = userPointDAO.getByUserId(userid);
			if(null != userPoint) {
				UserPointLogDO userPointLog = new UserPointLogDO();
				userPointLog.setPointId(userPoint.getId());
				userPointLog.setChangeType(48);
				userPointLog.setChangeValue(10);
				userPointLog.setCreateTime(new Date());
				userPointLogDAO.save(userPointLog);
				userPoint.setPointValue(userPoint.getPointValue()+10);
				userPoint.setModifyTime(new Date());
				userPointDAO.update(userPoint);
			}
		}
	}

	@Override
	public void finishOrder(OrderInfoDTO orderInfo)  throws BizException{
		

	}

	@Override
	public void finishOrders(Set<Long> orderIdSet)  throws BizException{
		for(Long orderId : orderIdSet){
			//1.根据orderId判断下面的transaction是否都已完成，判断条件为是否还有trans_status = 20(计费中)的书籍，若有，则该订单没有完成，不需要更新。否则，直接更新完成状态。
			OrderTransDO orderTransDo = new OrderTransDO();
			orderTransDo.setOrderId(orderId);
			orderTransDo.setTransStatus(BizConstants.ORDER_TRANS_STATUS_20);
			int count = orderTransDAO.count(orderTransDo);
			if(count == 0) {	//如果没有，则直接更新完成状态
				OrderInfoDO orderInfoDo = new OrderInfoDO();
				orderInfoDo.setId(orderId);
				orderInfoDo.setStatus(BizConstants.ORDER_STATUS_30);
				orderInfoDo.setModifyTime(new Date());
				orderInfoDAO.update(orderInfoDo);
			}
		}
	}

	@Override
	public void gridCharge(Long userid, String gridCode, Long gridTransId)  throws BizException{
		//1.先判断单人、单书格是否已经扣过款
		BookGridChargeLogDO chargeLogQuery = new BookGridChargeLogDO();
		chargeLogQuery.setGridCode(gridCode);
		chargeLogQuery.setUserId(userid);
		chargeLogQuery.setChargeDate(new Date());
		int count = bookGridChargeLogDAO.count(chargeLogQuery);
		if(count != 0) {	//说明当天、该人、该书格已经扣过款了，不再重复扣款。
			return ;
		}
		//2.判断单人，单书格打开是否超过15分钟。
		BookGridTransDO query = new BookGridTransDO();
		query.setUserId(userid);
		query.setUserType(BizConstants.GRID_TRANS_USER_TYPE_0);
		query.setGridCode(gridCode);
		query.setPresentDate(new Date());
		Integer remainSeconds = bookGridTransDAO.getRemainingSeconds(query);
		if(null == remainSeconds)
			remainSeconds = 0;
		if(remainSeconds > 600) {	//如果大于600，则说明超过十分钟，则需要进行额外扣款。
			String chargeAmountStr = configInfoManager.getValue("over600");
			//1.账号现金表变更
			AccountCashDO accountCash = accountCashDAO.getByUserid(userid);
			accountCash.setCashAmount(accountCash.getCashAmount().subtract(new BigDecimal(chargeAmountStr)));
			accountCash.setModifyTime(new Date());
			accountCashDAO.update(accountCash);
			//2.账户现金记录表增加
			AccountCashLogDO cashLogDO = new AccountCashLogDO();
			cashLogDO.setAccountCashId(accountCash.getId());
			cashLogDO.setChangeAmount(new BigDecimal(chargeAmountStr));
			cashLogDO.setCreateTime(new Date());
			cashLogDO.setOperType(BizConstants.ACCOUNT_CASH_OPER_TYPE_20);
			cashLogDO.setChargeType(BizConstants.ACCOUNT_CASH_CHARGE_TYPE_40);
			accountCashLogDAO.insert(cashLogDO);
			//3.书格扣款记录表增加
			BookGridChargeLogDO chargeLog = new BookGridChargeLogDO();
			chargeLog.setChargeAmount(new BigDecimal(chargeAmountStr));
			chargeLog.setChargeDate(new Date());
			chargeLog.setCreateTime(new Date());
			chargeLog.setGridCode(gridCode);
			chargeLog.setGridTransId(gridTransId);
			chargeLog.setUserId(userid);
			//bookGridChargeLog增加支付流水号字段---现金账户记录表中的ID
			chargeLog.setPaySerialNo(cashLogDO.getId());
			bookGridChargeLogDAO.insert(chargeLog);
		}
		//否则，就不继续进行
	}

	/**
	 * 获取用户扣费标志对象
	 * @param userId 用户ID
	 * @return
	 */
	private UserCostFlagDO getUserCostFlag(Long userId) {
		UserCostFlagDO flag = null ;
		flag = userCostFlagDAO.getByUserId(userId);
		if(null == flag) {
			return null;
		}
		Integer costOrder = flag.getCostOrder();
		BigDecimal remainder = flag.getRemainder();
		if(4 == costOrder || 3 == costOrder) {
			Date endTime = flag.getEndTime();
			if(DateFormatUtil.getMaxTimeDay(endTime).compareTo(new Date()) < 0) {
				flag.setValidFlag(0);
				flag.setModifyTime(new Date());
				userCostFlagDAO.update(flag);
				return getUserCostFlag(userId);
			}else {
				return flag;
			}
		}else if(2 == costOrder){
			if(remainder.compareTo(new BigDecimal("0.00")) <= 0) {
				flag.setValidFlag(0);
				flag.setModifyTime(new Date());
				userCostFlagDAO.update(flag);
				return getUserCostFlag(userId);
			}else {
				return flag;
			}
		}
		return flag;
	}
	@Override
	public void bookCharge() throws BizException {
		//每天凌晨执行任务
		//1.查询出所有未还的订单信息
		List<BookChargeDO> list = orderTransDAO.getRentBookList();
		
		//2.进行扣费处理
		for(BookChargeDO orderTrans : list) {
			//2.1查询现金账户
			try {
				Long userId = orderTrans.getUserId();
				UserInfoDO userInfo = userInfoDAO.get(userId);
				if(1 == userInfo.getUserType()) {
					logger.info("对用户[{}]的订单流水号[{}]进行凌晨扣费..由于是运维人员下架图书，不进行扣费.", userId, orderTrans.getId());
					continue;
				}
				if(System.currentTimeMillis() - orderTrans.getCreateTime().getTime() <= 1000*300) {
					logger.info("对用户[{}]的订单流水号[{}]进行凌晨扣费..由于不满5分钟，不进行扣费.", userId, orderTrans.getId());
					continue;
				}
				if(null == orderTrans.getPrice() || new BigDecimal("0.00").compareTo(orderTrans.getPrice()) == 0) {
					logger.info("对用户[{}]的订单流水号[{}]进行凌晨扣费..由于没有该图书信息或者图书单价为0.00，不进行扣费.", userId, orderTrans.getId());
					continue;
				}
				logger.info("对用户[{}]的订单流水号[{}]进行凌晨扣费开始...", userId, orderTrans.getId());
				AccountCashDO accountCash = accountCashDAO.getByUserid(userId);
				//2.2查询用户扣费标志表
				UserCostFlagDO userCostFlagResult = getUserCostFlag(userId);
				BigDecimal cost_per_book_per_day = orderTrans.getBorrowPrice();
				BigDecimal cost_per_book_over_3 = new BigDecimal(configInfoManager.getValue("cost_per_book_over_3"));
				BigDecimal cost = cost_per_book_per_day;	//计费金额默认为当天扣费金额
				Integer costFlag = 0;
				if(null != userCostFlagResult) {
					Integer costOrder = userCostFlagResult.getCostOrder();
					//如果已经是月卡用户或者年卡用户，并且borrowPrice为0，则不进行收费
					if(new BigDecimal("0.00").compareTo(cost_per_book_per_day) == 0 && (3 == costOrder || 4 == costOrder)) {
						//FIXME 用户如果借了5本书，但是年卡今天到期时，多出的两本书如何收费？还是不收费。
						if(3 == costOrder) {
							costFlag = 2;
						}else{
							costFlag = 3;
						}
						if(3 == costOrder) {//如果年卡到期之后，超过三本的图书按照每天2元收费
							int count = orderTransDAO.countByVIPCharge(userId);
							if(count > 3) {
								OrderTransDO query = new OrderTransDO();
								query.setUserId(userId);
								query.setId(orderTrans.getId());
								Integer rank = orderTransDAO.getRankByVIPQuery(query);
								if(rank != null && rank.intValue() > 3) {
									cost_per_book_per_day = cost_per_book_over_3;
									costFlag = 1;
								}
								
							}
						}
					}else if(4 == costOrder) { //如果是年卡会员，并且扣费金额不为0,判断用户在借图书使用vip计费的本书
						int count = orderTransDAO.countByVIPCharge(userId);
						if(count < 5) {
							cost_per_book_per_day = new BigDecimal("0.00");
							costFlag = 3;
						}
					}else if(3 == costOrder) { //如果是月卡会员，并且扣费金额不为0,判断用户在借图书使用vip计费的本书
						int count = orderTransDAO.countByVIPCharge(userId);
						if(count < 3) {
							costFlag = 2;
							cost_per_book_per_day = new BigDecimal("0.00");
						}
					}else {	//FIXME 如果用户年卡到期，或者月卡到期，5本书或者3本书 该如何扣费？
						BigDecimal sub = null;
						if(cost_per_book_over_3.compareTo(cost_per_book_per_day) != 0) {
							OrderTransDO query = new OrderTransDO();
							query.setUserId(userId);
							query.setBorrowPrice(cost_per_book_per_day);
							int count = orderTransDAO.countByUserIdAndBorrowPrice(query);
							if(count > 3) {	//如果大于3本，则扣费金额为2元每天
								cost_per_book_per_day = cost_per_book_over_3;
								costFlag = 1;
							}else {
								sub = userCostFlagResult.getRemainder().subtract(userCostFlagResult.getPrice());
								cost_per_book_per_day = userCostFlagResult.getPrice();
							}
							
						}else{
							sub = userCostFlagResult.getRemainder().subtract(cost_per_book_over_3);
							costFlag = 1;
						}
						userCostFlagResult.setRemainder(sub);
						userCostFlagResult.setModifyTime(new Date());
						if(sub.compareTo(new BigDecimal("0.00")) <= 0) {
							userCostFlagResult.setValidFlag(0);
						}
						userCostFlagDAO.update(userCostFlagResult);
					}
				}else if(new BigDecimal("0.00").compareTo(cost_per_book_per_day) == 0) { //如果年卡或者月卡到期，并且从userCostFlag表中查不到数据的话，则直接扣除余额
					OrderTransDO query = new OrderTransDO();
					query.setUserId(userId);
					query.setBorrowPrice(new BigDecimal("0.00"));
					int price0Count = orderTransDAO.countByUserIdAndBorrowPrice(query);
					query.setBorrowPrice(new BigDecimal("1"));
					int price1Count = orderTransDAO.countByUserIdAndBorrowPrice(query);
					int count = price0Count + price1Count;
					if(count > 3) {
						OrderTransDO rankQuery = new OrderTransDO();
						rankQuery.setUserId(userId);
						rankQuery.setId(orderTrans.getId());
						Integer rank = orderTransDAO.getRankByVIPQuery(rankQuery);
						if(rank != null && rank < 4) {
							cost_per_book_per_day = new BigDecimal(configInfoManager.getValue("cost_per_book_per_day"));
							costFlag = 0;
						}else {
							cost_per_book_per_day = cost_per_book_over_3;
							costFlag = 1;
						}
					}else {
						cost_per_book_per_day = new BigDecimal(configInfoManager.getValue("cost_per_book_per_day"));
						costFlag = 0;
					}
				}else if(cost_per_book_per_day.compareTo(cost_per_book_over_3) == 0) {
					OrderTransDO query = new OrderTransDO();
					query.setUserId(userId);
					query.setBorrowPrice(new BigDecimal("1.00"));
					int price1Count = orderTransDAO.countByUserIdAndBorrowPrice(query);
					if(price1Count < 3) {
						cost_per_book_per_day = new BigDecimal("1.00");
						costFlag = 0;
					}
				}
				if(cost_per_book_per_day.compareTo(cost_per_book_over_3) == 0) {
					costFlag = 1;
				}
				//2.3更新orderTrans表信息
				if(orderTrans.getTransAmount() != null){
					cost =orderTrans.getTransAmount().add(cost_per_book_per_day);
				}else {
					cost = cost_per_book_per_day;
				}
				if(cost.divide(orderTrans.getPrice(), 2, BigDecimal.ROUND_HALF_UP).compareTo(new BigDecimal("0.70")) >= 0) {
					//3.判断是否  用户借阅费用，每本的借阅费用超过此本书籍的价格的70%，自动停止计费，此本书不需用户归还，在借阅历史中显示“无需归还”, 状态设置为40
					orderTrans.setTransStatus(40);
					orderTrans.setModifyTime(new Date());
					
					String rfidCode = orderTrans.getRfidCode();
					BookEntityDO bookEntity = bookEntityDAO.get(rfidCode);
					String isbn = bookEntity.getIsbnNo();
					
					UserWishListDO condition = new UserWishListDO();
					condition.setDelFlag(0);
					condition.setIsbn(isbn);
					condition.setStatus(1);
					condition.setUserId(userId);
					UserWishListDO wl = userWishListDAO.getByCondition(condition);
					//更新心愿单信息
					if(null != wl) {
						wl.setStatus(2);
						wl.setModifyTime(new Date());
						userWishListDAO.update(wl);
					}
					
					//借阅费用已达上限 发送超过70%的短信
//					WxAPPMessagePushService.sendBorrowFeeOverPriceNotice(bookEntity.getIsbnNo(), orderTrans.getPrice().toString(), cost.toString(), userId);
					
				}
				orderTrans.setCostFlag(costFlag);
				orderTrans.setTransAmount(cost);
				orderTrans.setChargeCount(orderTrans.getChargeCount()+1);
				logger.info("对用户[{}]订单流水号[{}]本次扣费金额: [{}]", userId, orderTrans.getId(), cost_per_book_per_day.doubleValue());
				orderTrans.setBorrowPrice(cost_per_book_per_day);
				orderTransDAO.update(orderTrans);
				
				//2.4更新accountCash表以及新增accountCashLog表
				if(null != cost_per_book_per_day && new BigDecimal("0.00").compareTo(cost_per_book_per_day) != 0) {
					accountCash.setCashAmount(accountCash.getCashAmount().subtract(cost_per_book_per_day));
					accountCash.setModifyTime(new Date());
					accountCashDAO.update(accountCash);
					AccountCashLogDO accountCashLog = new AccountCashLogDO();
					accountCashLog.setAccountCashId(accountCash.getId());
					accountCashLog.setChangeAmount(cost_per_book_per_day);
					accountCashLog.setChargeType(BizConstants.ACCOUNT_CASH_CHARGE_TYPE_50);
					accountCashLog.setOperType(BizConstants.ACCOUNT_CASH_OPER_TYPE_20);
					accountCashLog.setCreateTime(new Date());
					accountCashLog.setOrderId(orderTrans.getId());
					accountCashLogDAO.insert(accountCashLog);
				}
			}catch(Exception e) {
				logger.error("扣费失败", e);
			}
		}
	}

	@Override
	public void readStatistics() throws BizException {
		//查询总借阅数量
		List<UserReadStatisticsDO> totalRecord = userReadStatisticsDAO.getTotalRecordListFromOrderTrans();
		if(CollectionUtils.isEmpty(totalRecord)) {
			logger.info("readStatistics's totalRecord is empty");
			return ;
		}
		Map<Long, UserReadStatisticsDO> map = new HashMap<Long, UserReadStatisticsDO>();
		for(UserReadStatisticsDO urs : totalRecord) {
			map.put(urs.getUserId(), urs);
		}
		//查询月借阅数量
		List<UserReadStatisticsDO> monthRecord = userReadStatisticsDAO.getMonthRecordListFromOrderTrans();
		if(!CollectionUtils.isEmpty(monthRecord)) {
			for(UserReadStatisticsDO mr : monthRecord) {
				map.get(mr.getUserId()).setMonthCount(mr.getMonthCount());
				map.get(mr.getUserId()).setMonthCumulativeTime(mr.getMonthCumulativeTime());
			}
		}
		//查询周借阅数量
		List<UserReadStatisticsDO> weekRecord = userReadStatisticsDAO.getWeekRecordListFromOrderTrans();
		if(!CollectionUtils.isEmpty(weekRecord)) {
			for(UserReadStatisticsDO wr : weekRecord) {
				map.get(wr.getUserId()).setWeekCount(wr.getWeekCount());
				map.get(wr.getUserId()).setWeekCumulativeTime(wr.getWeekCumulativeTime());
			}
		}
		
		Set<Long> idSet = map.keySet();
		for(Long userId : idSet) {
			UserReadStatisticsDO  ursDO = userReadStatisticsDAO.getByUserId(userId);
			if(null == ursDO) {
				ursDO = map.get(userId);
				ursDO.setId(UUID.randomUUID().toString().replaceAll("-", ""));
				ursDO.setCreateTime(new Date());
				userReadStatisticsDAO.insert(ursDO);
			}else {
				UserReadStatisticsDO newUrsDO = map.get(userId);
				newUrsDO.setId(ursDO.getId());
				newUrsDO.setCreateTime(ursDO.getCreateTime());
				newUrsDO.setModifyTime(new Date());
				userReadStatisticsDAO.updateByPrimaryKey(newUrsDO);
			}
		}
	}

	@Override
	public void updateByBuyBook(Long orderTransId) throws BizException {
		
		OrderTransDO orderTrans = orderTransDAO.get(orderTransId);
		if(null != orderTrans) {
			orderTrans.setTransStatus(BizConstants.ORDER_TRANS_STATUS_50);
			orderTrans.setModifyTime(new Date());
			if(null == orderTrans.getTransAmount()) {
				orderTrans.setTransAmount(new BigDecimal("0.00"));
			}
			orderTransDAO.update(orderTrans);
			String rfidCode = orderTrans.getRfidCode();
			BookEntityDO be = bookEntityDAO.get(rfidCode);
			be.setBorrowedStatus(BizConstants.BOOK_BORROW_STATUS_3);
			be.setModifyTime(new Date());
			bookEntityDAO.update(be);
		}
		
	}

	@Override
	public void discardOrderTrans(Long orderTransId) throws BizException {
		//查出orderTrans
		OrderTransDO orderTrans = orderTransDAO.get(orderTransId);
		orderTrans.setTransStatus(BizConstants.ORDER_TRANS_STATUS_60);
		orderTrans.setModifyTime(new Date());
		orderTransDAO.update(orderTrans);
		//查询bookEntity
		String rfidCode = orderTrans.getRfidCode();
		BookEntityDO bookEntity = bookEntityDAO.get(rfidCode);
		bookEntity.setBorrowedStatus(BizConstants.BOOK_BORROW_STATUS_4);
		bookEntity.setModifyTime(new Date());
		bookEntityDAO.update(bookEntity);
		//修改用户其他在借图书
		Long userId = orderTrans.getUserId();
		
		List<OrderTransDO> list = orderTransDAO.getBorrowingListByUserId(userId);
		if(CollectionUtils.isEmpty(list))
			return ;
		for(OrderTransDO ot : list) {
			Integer costFlag = ot.getCostFlag();
			//如果是包月免费或者包年免费,则直接跳过.
			if(2 == costFlag || 3 == costFlag) {
				continue;
			}
			Integer cf = getCostFlag(userId);
			if(2 == cf) {	//月卡免费
				int count = orderTransDAO.countByVIPCharge(userId);
				if(count < 3) {
					ot.setBorrowPrice(new BigDecimal("0.00"));
					ot.setCostFlag(cf);
					orderTransDAO.update(ot);
				}
			}else if(3 == cf) {	//年卡免费
				int count = orderTransDAO.countByVIPCharge(userId);
				if(count < 5) {
					ot.setBorrowPrice(new BigDecimal("0.00"));
					ot.setCostFlag(cf);
					orderTransDAO.update(ot);
				}
			}else {	//正常扣费
				OrderTransDO query = new OrderTransDO();
				query.setUserId(userId);
				query.setBorrowPrice(new BigDecimal("1.00"));
				int count = orderTransDAO.countByUserIdAndBorrowPrice(query);
				if(count < 3) {
					ot.setBorrowPrice(new BigDecimal("1.00"));
					ot.setCostFlag(0);
					orderTransDAO.update(ot);
				}
			}
		}
	}
	
	private Integer getCostFlag(Long userId) {
		UserCostFlagDO userCostFlag = userCostFlagDAO.getByUserId(userId);
		if(null == userCostFlag) {
			return 0;
		}
		if(3 == userCostFlag.getCostOrder()) {
			return 2;
		}
		if(4 == userCostFlag.getCostOrder()) {
			return 3;
		}
		return 0;
	}
	
}
